package sdk3.components.remoteService
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.StatusEvent;
	import flash.net.NetConnection;
	import flash.net.Responder;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Button;
	import mx.rpc.Fault;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	import mx.utils.ObjectProxy;
	
	import singleton.singleton_storage;

	public class remoteService_utility extends EventDispatcher
	{
		/*******************************************************************************
		 * Software: remoteService_utility.as												
		 * Version:  1.1
		 * Date:     2010_12_21_TIME_08:44:18
		 * Author:    
		 * LICENSE:  GNU General Public License (http://www.gnu.org/licenses/gpl.html) 	 *  	 * English: 		This program is free software; 		you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; 		either version 3 of the License, or (at your option) any later version.   		This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 		without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 		See the GNU General Public License for more details. 		You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.   		 * Excerpt English: 		 * Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), 		 * that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things   		Auf Deutsch: 		Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, 		weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version. 		Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 		sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. 		Details finden Sie in der GNU General Public License. 		Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. 		Falls nicht, siehe <http://www.gnu.org/licenses/>.   		 * Auszug Deutsch: 		 * Wenn wir von freier Software sprechen, so beziehen wir uns auf Freiheit, nicht auf den Preis. 		 * Unsere Allgemeinen Öffentlichen Lizenzen sind darauf angelegt, sicherzustellen, daß Sie die Freiheit haben, 		 * Kopien freier Software zu verbreiten (und dafür etwas zu berechnen, wenn Sie möchten), die Möglichkeit, 		 * daß Sie die Software als Quelltext erhalten oder den Quelltext auf Wunsch bekommen, daß Sie die Software 		 * ändern oder Teile davon in neuen freien Programmen verwenden dürfen und daß Sie wissen, daß Sie dies alles tun dürfen.   GNU General Public License (http://www.gnu.org/licenses/gpl.html)
		 * 
		 * English:
		 This program is free software;
		 you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation;
		 either version 3 of the License, or (at your option) any later version.
		 
		 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
		 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
		 See the GNU General Public License for more details.
		 You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
		 
		 * Excerpt English:
		 * Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish),
		 * that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things
		 
		 Auf Deutsch:
		 Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht,
		 weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
		 Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
		 sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK.
		 Details finden Sie in der GNU General Public License.
		 Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben.
		 Falls nicht, siehe <http://www.gnu.org/licenses/>.
		 
		 * Auszug Deutsch:
		 * Wenn wir von freier Software sprechen, so beziehen wir uns auf Freiheit, nicht auf den Preis.
		 * Unsere Allgemeinen Öffentlichen Lizenzen sind darauf angelegt, sicherzustellen, daß Sie die Freiheit haben,
		 * Kopien freier Software zu verbreiten (und dafür etwas zu berechnen, wenn Sie möchten), die Möglichkeit,
		 * daß Sie die Software als Quelltext erhalten oder den Quelltext auf Wunsch bekommen, daß Sie die Software
		 * ändern oder Teile davon in neuen freien Programmen verwenden dürfen und daß Sie wissen, daß Sie dies alles tun dürfen.
		 * 
		 * PURPOSE:
		 defines connection parameters that can be globally accessed like:
		 o the path & filenameto php servers/endpoints to connect to.
		 o what database to use.
		 * 
		 * i tried to keep the layout as simple and compact as possible.
		 
		 Usage:
		 * backend interaction
		 * e.g. onXMLResult and onXMLFault handle the Results and Faults from the java backend that
		 * transmitts its data in xml format. actually its a mix of csv and xml style.
		 * for easier decoding by flash player xml is used. 

 		 * FEATURES:
		 * 
		 * TODO: XXX:
		CHANGELOG / CREDITS:
		WHO?							| WHAT?															| PRECIOUS TIME SPEND?	| WHY?
								 		| increase login count after login								| 1h					     | cause its cool

 		 * USAGE EXAMPLE: WITH EVENT LISTENER
		 **/

		public function remoteService_utility()
		{
		}

		/** ======== VARS ======== **/
		public var verbose_status:Boolean = true; /** do not output certain status messages. (spamming the console) **/
		public var verbose_error:Boolean = true; /** output errors to console **/
		
		//		public var static instance:remoteService2 = null; // STATIC!
		public var responder:Responder;
		public var connection:NetConnection;
		
		public var LENGTH:int = 0;
		public var counter:int = 0;
		
		public var ARRAY_FILTERED:Array = new Array(); // array ohne status meldung
		
		public var METHOD:String = '';
		
		import sdk3.c_STRING;
		public var c_STRING_inst:c_STRING = new c_STRING(); // toolbox for dealing with strings
		
		import sdk3.c_ARRAY;
		public var c_ARRAY_inst:c_ARRAY = new c_ARRAY();
		
		import sdk3.c_XML;
		public var c_XML_inst:c_XML = new c_XML();
		
		import sdk3.c_MATH;
		public var c_MATH_inst:c_MATH = new c_MATH();
		
		import sdk3.c_OBJECT;
		public var c_OBJECT_inst:c_OBJECT = new c_OBJECT();
		
		import sdk3.c_formaters;
		public var c_formaters_inst:c_formaters = new c_formaters();
		
		import sdk3.c_DATE;
		public var c_DATE_inst:c_DATE = new c_DATE();
		
		import sdk3.c_VALIDATORS;
		public var c_VALIDATORS_inst:c_VALIDATORS = new c_VALIDATORS();
		
		/** currently used endpoint, will be set during constructor execution **/
		/**
		 * local stores of connection parameters:
		 * ['url']
		 * -> path and filename.php where one's endpoints script are on one's php-powered-webserver
		 * eg. http://localhost/onesproject/endpoint_method.php 
		 * ['class_name']
		 * -> simply the name of the endpoint script, will be automatically generated and extracted from url when calling a service function.
		 * **/
		/** currently used Database, will be set during constructor execution **/
		public var connectionParameters_:connectionParameters = null;

		/** merkt sich das letzte Ergebnis des zuletzt gelieferten XML-Service **/
		public var lastXMLResult:Array = new Array();
		
		/** accesspoint to access last result **/
		public var rpcResult:Array = new Array();
		
		/** responsible for doing post/get-requests to php with XML results **/
		public var HTTPSERVICE_XML:HTTPService = new HTTPService();
		
		/** sort on this property, if nothing specified '' no sorting will be done on the result. **/
		public var SortField:String = '';
		
		/** how the result should be sorted, possible values are ASC = ascending, DSC = descending **/
		public var SortMode:String = 'ASC';
		
		/**
		 * language -> in what language should the status messages be displayed?
		 * currently available:
		 * EN -> english
		 * DE -> german (default)
		 * **/
		public var language:String = 'DE';
		
		/** currently used labels, that will show service-status messages for user and eveloper (more detailed, technical output)
		 * **/
		public var USER_LABEL_STATUS:Object = {text:''};
		public var DEV_LABEL_STATUS:Object = {text:''};

		/** 
		 var loop_count:int = 0;
		 var NUMBER_ELEMENTS:int = 0; -> anzahl der elemente in der table
		 var paging_active:Boolean = false;
		 var ARRAY_PAGING:Array = new Array(); <- stores requests and results of the paging process
		 var packet_size:int = 30;
		 *  results -> are the results of all pages currently fetched, it may not includes all results, until all pages are loaded.
		 * loading_bar -> 
		 **/
		public var OBJECT_PAGING_XML:Object = {packet_size:0,
			loop_count:0,
			NUMBER_ELEMENTS:0,
			paging_active:false,
			loop_count_elements_active:false,
			DatabaseName:'',
			TableName:'',
			ARRAY_PAGING:new Array(),
			results:new Array(),
			requests:new Array(),
			loading_bar:Object,
			METHOD:''
		};
		
		/** gibt ausschluss über eventuelle fehler aber auch erfolgsmeldungen.
		 STATUS['status'] -> status, erfolgs aber auch fehlermeldungen werden alles hier gespeichert. 
		 STATUS['result'] -> das ergebnis des http services, bei read operationen die angeforderten daten, 
		 * bei schreib operationen/update/delete etc. das die erfolgs-meldung.
		 STATUS['mode'] -> INSERT, UPDATE, READ or SQL 
		 STATUS['type'] -> ob es sich um einen Fault oder ein Result handelt. 
		 
		 beispiel werte:
		 mode = "INSERT" : String	
		 result = Array (@1db07e41)	
		 status = "amfFault: XDBTOOLS: INSERT: on DATABASE: test TABLE: AMFPHP_TEST_TABLE ERROR. \n query: please check error.log, query should be there. \n SQL ERROR: Table 'test.AMFPHP_TEST_TABLE' doesn't exist \n " : String	
		 type = "amfFault" : String
		 **/
		public var STATUS:Object = {mode:'',result:'',status:'',type:''};

		/** checks if all connection parameters are complete, otherwise uses default values.
		 * if parameters are missing, output a error message.
		 * **/
		public function CHECK_PARAMETERS(connectionParameters_:connectionParameters,METHOD:String,USER_LABEL_STATUS:Object = null,DEV_LABEL_STATUS:Object = null,SortMode = 'ASC',SortField = ''):Boolean
		{
			/** check connectionParameters_ **/
			var VALID:Boolean = false;
			
			VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'','remoteService2: CHECK_PARAMETERS: parameter connectionParameters_ is empty.');
			if(VALID)
			{
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'url','remoteService2: CHECK_PARAMETERS: connectionParameters_ parameter url is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'type','remoteService2: CHECK_PARAMETERS: connectionParameters_ parameter type is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'class_name','remoteService2: CHECK_PARAMETERS: connectionParameters_ parameter class_name is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'packet_size','remoteService2: CHECK_PARAMETERS: connectionParameters_ parameter packet_size is empty.');
			}
			if(VALID) { this.connectionParameters_ = connectionParameters_; }

			/** check labels **/
			if(DEV_LABEL_STATUS == null)
			{
				this.DEV_LABEL_STATUS = new Object();
			}
			else
			{
				this.DEV_LABEL_STATUS = DEV_LABEL_STATUS;
			}
			if(USER_LABEL_STATUS == null)
			{
				this.USER_LABEL_STATUS = new Object(); 
			}
			else
			{
				this.USER_LABEL_STATUS = USER_LABEL_STATUS;
			}

			if(c_OBJECT_inst.empty(connectionParameters_['DatabaseName']))
			{
				var ERROR:String =  " remoteService_utility: no DatabaseName given. can not proceed.";
				throw new Error(ERROR);
			}

			VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_['DatabaseName'],'','remoteService2: CHECK_PARAMETERS: parameter Database is empty.');
			
			if(VALID)
			{
				/** validate Database config object **/
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'DatabaseName','remoteService2: CHECK_PARAMETERS: property DatabaseNameName is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'type','remoteService2: CHECK_PARAMETERS: Database-type is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'port','remoteService2: CHECK_PARAMETERS: property port is empty.');
				VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'user','remoteService2: CHECK_PARAMETERS: property usr is empty.');
				IF_PROPERTY_EMPTY_OR_MISSING_ERROR(connectionParameters_,'password','remoteService2: CHECK_PARAMETERS: password is empty, this is valid but could be a security risk!');
			}
			
			VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(METHOD,'','remoteService2: CHECK_PARAMETERS:  parameter METHOD is empty.');
			if(VALID)
			{
				this.METHOD = METHOD;
			}
			
			/** how the result should be sorted, possible values are ASC = ascending, DSC = descending **/
			VALID = IF_PROPERTY_EMPTY_OR_MISSING_ERROR(this.SortMode,'','remoteService2: CHECK_PARAMETERS: parameter SortMode is empty, setting to default value \'ASC\'');
			
			if(VALID)
			{
				this.SortMode = SortMode;
			}
			else
			{
				this.SortMode = 'ASC';
				VALID = true;
			}
			
			if(VALID)
			{
				this.connectionParameters_ = connectionParameters_;
			}

			return VALID;
		}

		/** ======== RESULT & FAULT HANDLER ======== **/
		/** ======== XML ======== **/
		/** responsible for results in XML format **/
		/** when using paging lastXMLResult contains only one page of all records to be fetched **/
		public function onXMLResult(event:Event = null):Array
		{
			STATUS['status'] = 'xmlResult: '; // +c_STRING_inst.REPLACE_ALL('\n',' ',event.toString());
			
			lastXMLResult = new Array();
			
			if(event.type == 'result')
			{
				if(event['result'] == "")
				{
					lastXMLResult = null;
				}
				else if(event['result'].sqlxml == null) // kein ergebnis
				{
					lastXMLResult = null;
				}
				else
				{
					if(event['result']['sqlxml']['record'] is ObjectProxy)
					{
						// single object returned
						lastXMLResult.push(event['result']['sqlxml']['record']);
					}
					if(event['result']['sqlxml']['record'] is Array)
					{	// multiple objects returned
						lastXMLResult = c_ARRAY_inst.copy(event['result']['sqlxml']['record']);
					}
					if(event['result']['sqlxml']['record'] is ArrayCollection)
					{	// multiple objects returned
						lastXMLResult = c_ARRAY_inst.copy(event['result']['sqlxml']['record']['source']);
						// lastXMLResult = c_ARRAY_inst.CONCAT(lastXMLResult,event['result']['sqlxml']['record'].source.slice());
					}
				}
				
				if(OBJECT_PAGING_XML['paging_active'] && (OBJECT_PAGING_XML['loop_count_elements_active'] == false) && (OBJECT_PAGING_XML['loop_count'] <= OBJECT_PAGING_XML['requests']['length']-1))
				{
					this.rpcResult = OBJECT_PAGING_XML['results'] = c_ARRAY_inst.CONCAT_B(lastXMLResult,OBJECT_PAGING_XML['results']);
					FUNC_SET_PROGRESS(this.rpcResult.length,OBJECT_PAGING_XML['NUMBER_ELEMENTS'],OBJECT_PAGING_XML['loading_bar']);
					
					var PAGING_RESULT:PagingEvent = new PagingEvent('paging_result',lastXMLResult);
					this.dispatchEvent(PAGING_RESULT);
					
					var OBJECT:Object = OBJECT_PAGING_XML['requests'][OBJECT_PAGING_XML['loop_count']];
					
					OBJECT_PAGING_XML['loop_count'] = OBJECT_PAGING_XML['loop_count'] + 1;
					
					this.XML_READ_RANGE(OBJECT_PAGING_XML['DatabaseName'],OBJECT_PAGING_XML['TableName'],OBJECT['FROM'],OBJECT['TO']);
					
					// trace('COUNT: '+OBJECT_PAGING_XML['loop_count'].toString()+' FROM: '+(OBJECT_PAGING_XML['requests']['length']-1).toString());
				}
				else
				{
					// last element
					if(OBJECT_PAGING_XML['paging_active'])
					{
						OBJECT_PAGING_XML['paging_active'] = false;
						
						OBJECT_PAGING_XML['results'] = c_ARRAY_inst.CONCAT_B(lastXMLResult,OBJECT_PAGING_XML['results']);
						this.rpcResult = OBJECT_PAGING_XML['results'];
						FUNC_SET_PROGRESS(this.rpcResult.length,OBJECT_PAGING_XML['NUMBER_ELEMENTS'],OBJECT_PAGING_XML['loading_bar']);
						
						/** o auch bei paging darf die letzte page nicht über eventResult kommen, sondern sollte auch über paging event kommen. **/
						var PAGING_RESULT:PagingEvent = new PagingEvent('paging_result',lastXMLResult);
						this.dispatchEvent(PAGING_RESULT);
					}

					/** 'status' event? welches status messages zurückliefert wie
					 * LISTE DER STATUS EVENTS:
					 * 'empty result' -> result der sql query war leer. (kein fehler, nur evtl keine daten vorhanden d.h. table empty)
					 * **/
					if(lastXMLResult != null)
					{
						if(lastXMLResult[0] != null)
						{
							if(lastXMLResult[0]['status'] != null)
							{
								/** server status messages **/
								if(lastXMLResult[0]['status'] == 'empty result')
								{
									STATUS['mode'] = 'STATUS';
									STATUS['result'] = new Array();
									if(language == 'EN')
									{
										STATUS['status'] = 'No Datarecords available.';
									}
									else if(language == 'DE')
									{
										STATUS['status'] = 'Keine Datensätze vorhanden.';
									}
									
									var STATUS_EVENT:StatusEvent = new StatusEvent('status',false,false,lastXMLResult[0]['status'],'message from the server');
									this.dispatchEvent(STATUS_EVENT);
								}
								/** server status messages **/
								else if(lastXMLResult[0].hasOwnProperty("MYSQLERROR"))
								{
									STATUS['mode'] = 'STATUS';
									STATUS['result'] = new Array();
									STATUS['status'] = lastXMLResult[0]["MYSQLERROR"];
									
									var STATUS_EVENT:StatusEvent = new StatusEvent('status',false,false,lastXMLResult[0]['status'],'message from the server');
									this.dispatchEvent(STATUS_EVENT);
								}
								/** server status messages **/
								else if(lastXMLResult[0]['status'].toString().substring(0,59) == 'Error: No connection to database. Is MySQL Service running?')
								{
									STATUS['mode'] = 'STATUS';
									STATUS['result'] = new Array();
									if(language == 'EN')
									{
										STATUS['status'] = lastXMLResult[0]['status'];
									}
									else if(language == 'DE')
									{
										STATUS['status'] = 'Server kann keine Verbindung zur Datenbank herstellen. Läuft der MySQL Datenbank dienst? :'+lastXMLResult[0]['status'];
									}
	
									var FAULT:Fault = new Fault(STATUS['status'],STATUS['status']);
									var FAULT_EVENT:FaultEvent = new FaultEvent(FaultEvent.FAULT,true,false,FAULT,null,null);
									
									//                                            REPLACE_ALL(REPLACE_THIS:String,REPLACEMENT:String,MATERIAL:String):String
									STATUS['status'] = 'xmlFault: '+c_STRING_inst.REPLACE_ALL('\n'               ,' '               ,STATUS['status']);
									UPDATE_DEV_LABEL_STATUS(STATUS);
									
									this.dispatchEvent(FAULT_EVENT); // einfache variante 			// this.dispatchEvent(new Event( 'amfFault' ));
								}
								/** if table is empty.... sollte da NUR ein paging event folgend oder SOWOHL paging event ALS AUCH result event? ich meine letzteres. **/
								else if(lastXMLResult[0]['status'] == 'empty result')
								{
									var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,OBJECT_PAGING_XML['results'],null,null);
									this.dispatchEvent(RESULT_EVENT);
								}
								/** server status messages **/
								else if(lastXMLResult[0]['status'] == 'success')
								{
									if(lastXMLResult[1] != null)
									{
										STATUS['mode'] = 'STATUS';
			
										/** 'normales' komplettes result ohne paging **/
										var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,c_ARRAY_inst.REMOVE_FIRST_ELEMENT(lastXMLResult),null,null);
										this.dispatchEvent(RESULT_EVENT);
									}
								}
								/** server status messages **/
								else if(lastXMLResult[0]['status'] == 'error')
								{
									if(lastXMLResult[1] != null)
									{
										STATUS['mode'] = 'STATUS';
			
										/** 'normales' komplettes result ohne paging **/
										var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,c_ARRAY_inst.REMOVE_FIRST_ELEMENT(lastXMLResult),null,null);
										this.dispatchEvent(RESULT_EVENT);
									}
								}
								/** registeration failed message, e.g. after insertIfNotExists **/
								else if(lastXMLResult[0]['status'] == 'user registration failed')
								{
									if(lastXMLResult[0]['RESULT'] == 'element does exist')
									{
										STATUS['mode'] = 'STATUS';

										/** if this insertIfNotExists was ment for user registration **/
										var REGISTER_EVENT:RegisterEvent = new RegisterEvent(RegisterEvent.FAULT_USER_ALLREADY_EXISTS,lastXMLResult[0]['RESULT']);
										this.dispatchEvent(REGISTER_EVENT);
										
										/** if this insertIfNotExists was NOT ment for user registration **/
										var FAULT:Fault = new Fault(lastXMLResult[0]['status'],lastXMLResult[0]['RESULT']);
										var FAULT_EVENT:FaultEvent = new FaultEvent(FaultEvent.FAULT,true,false,FAULT,null,null);
										this.dispatchEvent(FAULT_EVENT);
										// var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,c_ARRAY_inst.REMOVE_FIRST_ELEMENT(lastXMLResult),null,null);
										// this.dispatchEvent(RESULT_EVENT);
									}
								}
								else if(lastXMLResult[0]['status'] == 'insertIfNotExists failed')
								{
									if(lastXMLResult[0]['RESULT'] == 'element does exist')
									{
										STATUS['mode'] = 'STATUS';

										/** if this insertIfNotExists was NOT ment for user registration **/
										var FAULT:Fault = new Fault(lastXMLResult[0]['status'],lastXMLResult[0]['RESULT']);
										var FAULT_EVENT:FaultEvent = new FaultEvent(FaultEvent.FAULT,true,false,FAULT,null,null);
										this.dispatchEvent(FAULT_EVENT);
									}
								}
								else if(lastXMLResult[0]['status'] == 'insertIfNotExists successful')
								{
									if(lastXMLResult[0]['RESULT'] == 'element does not exist yet')
									{
										STATUS['mode'] = 'STATUS';

										var REGISTER_EVENT:RegisterEvent = new RegisterEvent(RegisterEvent.RESULT,lastXMLResult[0]['RESULT']);
										this.dispatchEvent(REGISTER_EVENT);
										
										/** dispatch result event **/
										var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,lastXMLResult,null,null);
										this.dispatchEvent(RESULT_EVENT);
									}
								}
								else if(lastXMLResult[0]['status'] == 'user registration successful')
								{
									if(lastXMLResult[0]['RESULT'] == 'user did not exist yet')
									{
										STATUS['mode'] = 'STATUS';

										var REGISTER_EVENT:RegisterEvent = new RegisterEvent(RegisterEvent.RESULT,lastXMLResult[0]['RESULT']);
										this.dispatchEvent(REGISTER_EVENT);
									}
								}
								
								/** login messages **/
								/**
								server responds with
									LOGIN_RESULT = have a nice day!
									status = login success
									
									LOGIN_RESULT = password did not match
									status = login failed
									
									LOGIN_RESULT = user does not exis
									status = login failed
								**/
								else if(lastXMLResult[0]['status'] == 'login success')
								{
									// status = login success
									// LOGIN_RESULT = have a nice day!
									if(lastXMLResult[0].hasOwnProperty('LOGIN_RESULT'))
									{
										if(lastXMLResult[0]['LOGIN_RESULT'] == 'have a nice day!')
										{
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = 'login successful: have a nice day!';
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'login erfolgreich: have a nice day!';
											}
	
											STATUS['mode'] = 'STATUS';
											
											/** 'normales' komplettes result ohne paging **/
											var LOGIN_EVENT:LoginEvent = new LoginEvent(LoginEvent.RESULT,lastXMLResult);
											this.dispatchEvent(LOGIN_EVENT);
										}
									}
								}
								else if(lastXMLResult[0]['status'] == 'login failed')
								{
									// status = login failed
	
									if(lastXMLResult[0].hasOwnProperty('LOGIN_RESULT'))
									{
									// LOGIN_RESULT = user does not exis
										if(lastXMLResult[0]['LOGIN_RESULT'] == 'user does not exis')
										{
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = lastXMLResult[0]['status'];
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'Login fehlgeschlagen: Username existiert nicht.';
											}
										}
										else if(lastXMLResult[0]['LOGIN_RESULT'] == 'password did not match')
										{
											// LOGIN_RESULT = password did not match
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = lastXMLResult[0]['status'];
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'Login fehlgeschlagen: Passwort stimmt nicht.';
											}
										}
										var FAULT:Fault = new Fault(STATUS['status'],STATUS['status']);
										var FAULT_LOGIN_EVENT:LoginEvent = new LoginEvent(LoginEvent.FAULT,FAULT);
										this.dispatchEvent(FAULT_LOGIN_EVENT);
									}
									
									if(lastXMLResult[1] != null)
									{
										STATUS['mode'] = 'STATUS';
										
										/** 'normales' komplettes result ohne paging **/
										var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,lastXMLResult,null,null);
										this.dispatchEvent(RESULT_EVENT);
									}
								}
								
								/** registration messages **/
								/**
								server responds with
									LOGIN_RESULT = have a nice day!
									status = login success
									
									LOGIN_RESULT = password did not match
									status = login failed
									
									LOGIN_RESULT = user does not exis
									status = login failed
								**/
								else if(lastXMLResult[0]['status'] == 'login success')
								{
									// status = login success
									// LOGIN_RESULT = have a nice day!
									if(lastXMLResult[0].hasOwnProperty('LOGIN_RESULT'))
									{
										if(lastXMLResult[0]['LOGIN_RESULT'] == 'have a nice day!')
										{
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = 'login successful: have a nice day!';
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'login erfolgreich: have a nice day!';
											}
	
											STATUS['mode'] = 'STATUS';
											
											/** 'normales' komplettes result ohne paging **/
											var LOGIN_EVENT:LoginEvent = new LoginEvent(LoginEvent.RESULT,lastXMLResult);
											this.dispatchEvent(LOGIN_EVENT);
										}
									}
								}
								else if(lastXMLResult[0]['status'] == 'login failed')
								{
									// status = login failed
	
									if(lastXMLResult[0].hasOwnProperty('LOGIN_RESULT'))
									{
									// LOGIN_RESULT = user does not exis
										if(lastXMLResult[0]['LOGIN_RESULT'] == 'user does not exis')
										{
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = lastXMLResult[0]['status'];
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'Login fehlgeschlagen: Username existiert nicht.';
											}
										}
										else if(lastXMLResult[0]['LOGIN_RESULT'] == 'password did not match')
										{
											// LOGIN_RESULT = password did not match
											STATUS['result'] = new Array();
											if(language == 'EN')
											{
												STATUS['status'] = lastXMLResult[0]['status'];
											}
											else if(language == 'DE')
											{
												STATUS['status'] = 'Login fehlgeschlagen: Passwort stimmt nicht.';
											}
										}
										var FAULT:Fault = new Fault(STATUS['status'],STATUS['status']);
										var FAULT_LOGIN_EVENT:LoginEvent = new LoginEvent(LoginEvent.FAULT,FAULT);
										this.dispatchEvent(FAULT_LOGIN_EVENT);
									}
									
									if(lastXMLResult[1] != null)
									{
										STATUS['mode'] = 'STATUS';
										
										/** 'normales' komplettes result ohne paging **/
										var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,lastXMLResult,null,null);
										this.dispatchEvent(RESULT_EVENT);
									}
								}
							}
							else
							{
								/** 'normales' komplettes result ohne paging **/
								STATUS['mode'] = 'READ';
								var RESULT_EVENT:ResultEvent = new ResultEvent(ResultEvent.RESULT,true,false,lastXMLResult,null,null);
								this.dispatchEvent(RESULT_EVENT);
							}
						}
						
					}
					
					UPDATE_DEV_LABEL_STATUS(STATUS);
					UPDATE_USER_LABEL_STATUS(STATUS);
				}
			}
			
			return lastXMLResult;
		}

		/** responsible for faults in XML format **/
		public function onXMLFault(event:Event = null):void
		{
			if(event.type == 'fault')
			{
				var FAULT:Fault = new Fault(event.toString(),event.toString());
				var FAULT_EVENT:FaultEvent = new FaultEvent(FaultEvent.FAULT,true,false,FAULT,null,null);
				
				if(verbose_error)
				{
					trace(event.toString());
				}
				
				//                                            REPLACE_ALL(REPLACE_THIS:String,REPLACEMENT:String,MATERIAL:String):String
				STATUS['status'] = 'xmlFault: '+c_STRING_inst.REPLACE_ALL('\n'               ,' '               ,event.toString());
				STATUS['mode'] = "STATUS";
				
				try
				{
					var FAULTDETAIL:String = event['message']['faultDetail'];
					if(FAULTDETAIL.substring(0,112) == "Error: [IOErrorEvent type=\"ioError\" bubbles=false cancelable=false eventPhase=2 text=\"Error #2032: Stream Error.")
					{
						if(language == 'EN')
						{
							STATUS['status'] = 'xmlFault: No connection to server. (ioError, Error #2032: Stream Error.) Is server running and reachable?';
						}
						else if(language == 'DE')
						{
							STATUS['status'] = 'xmlFault: Keine Verbindung zum Server. (ioError, Error #2032: Stream Error.) Läuft der Server und ist dieser erreichbar?';
						}
					}
				}
				catch(e:Error)
				{
				}
				
				STATUS['result'] = FaultEvent;
				UPDATE_DEV_LABEL_STATUS(STATUS);
				
				this.dispatchEvent(FAULT_EVENT); // einfache variante 			// this.dispatchEvent(new Event( 'amfFault' ));
			}
		}

		/** used method: XML
		 *  **/
		public function XML_READ_RANGE(DatabaseName:String,TableName:String,FROM:int = undefined,TO:int = undefined):void
		{
			if(TableName != null && DatabaseName != null && (FROM != undefined) && (TO != undefined))
			{
				if(OBJECT_PAGING_XML['paging_active'] == false)
				{
					rpcResult = new Array();  /** reset result array of this instance **/
				}
				HTTPSERVICE_XML = new HTTPService();
				
				if(HTTPSERVICE_XML.hasEventListener(ResultEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(ResultEvent.RESULT, onXMLResult);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(FaultEvent.FAULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(FaultEvent.FAULT, onXMLResult);
				}
				
				if(HTTPSERVICE_XML.hasEventListener(PagingEvent.RESULT) == false)
				{
					HTTPSERVICE_XML.addEventListener(PagingEvent.RESULT, onXMLResult);
				}
				
				HTTPSERVICE_XML.method="POST";
				
				HTTPSERVICE_XML.url = connectionParameters_['url'];
				
				HTTPSERVICE_XML.useProxy=false;
				HTTPSERVICE_XML.request['compressed'] = false; // true = not working yet
				
				var AMOUNT:int = TO - FROM;
				HTTPSERVICE_XML.request['query'] = "SELECT * FROM `"+DatabaseName+"`.`"+TableName+"`"+" LIMIT "+FROM+", "+AMOUNT+";";
				HTTPSERVICE_XML.send();
			}
			else
			{
				if(verbose_error)
				{
					trace('not enough parameters to execute READ_TABLE_XML');
				}
			}
		}

		/** checks if a given PROEPRTY of OBJECT is existing and has content **/
		public function IF_PROPERTY_EMPTY_OR_MISSING_ERROR(OBJECT:Object,PROPERTY:String,ERROR_MESSAGE:String):Boolean
		{
			var VALID:Boolean = false;
			
			if(PROPERTY != '' && PROPERTY != null)
			{
				if(OBJECT.hasOwnProperty(PROPERTY))
				{
					if(c_OBJECT_inst.empty(OBJECT[PROPERTY]))
					{
						VALID = false;
					}
					else
					{
						VALID = true;
					}
				}
			}
			else
			{
				if(c_OBJECT_inst.empty(OBJECT))
				{
					VALID = false;
				}
				else
				{
					VALID = true;
				}
			}
			
			
			if(verbose_error)
			{
				if(VALID == false)
				{
					trace(ERROR_MESSAGE);
				}
			}
			
			return VALID;
		}

		/** update labelstatus of dev **/
		public function UPDATE_DEV_LABEL_STATUS(STATUS:Object):void
		{
			if(DO_NOT_UPDATE_DEV_LABEL_STATUS)
			{
				return;
			}

			/** update labelstatus **/
			if(DEV_LABEL_STATUS != null)
			{
				if(STATUS['type'] == 'amfResult')
				{
					var ARRAY:Array = null;
					try
					{
						ARRAY = STATUS['result'];
					}
					catch(e:Error)
					{
					}
					
					try
					{
						if(ARRAY.length == 0)
						{
							this.USER_LABEL_STATUS.text = 'Keine Daten vorhanden.';
						}
						else
						{
							if(STATUS['mode'] == 'READ') 	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich geladen.'; }
							else if(STATUS['mode'] == 'INSERT')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich gespeichert.'; }
							else if(STATUS['mode'] == 'UPDATE')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich aktualisisert.'; }
							else if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Abfrage erfolgreich.'; }
							else if(STATUS['mode'] == 'COUNT_ELEMENTS') { this.DEV_LABEL_STATUS.text = STATUS['mode']+' Elemente erfolgreich gezählt.'; }
							else if(STATUS['mode'] == 'STATUS') { this.DEV_LABEL_STATUS.text = STATUS['status']; }
							else { this.DEV_LABEL_STATUS.text = ' Abfrage erfolgreich '; }
						}
					}
					catch(e:Error)
					{
					}
					
					if(ARRAY == null)
					{
						if(STATUS['mode'] == 'READ')
						{
							this.USER_LABEL_STATUS.text = 'Keine Daten vorhanden.';
						}
						else
						{
							if(STATUS['mode'] == 'READ') 	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich geladen.'; }
							else if(STATUS['mode'] == 'INSERT')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich gespeichert.'; }
							else if(STATUS['mode'] == 'UPDATE')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich aktualisisert.'; }
							else if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Abfrage erfolgreich.'; }
							else if(STATUS['mode'] == 'COUNT_ELEMENTS') { this.DEV_LABEL_STATUS.text = STATUS['mode']+' Elemente erfolgreich gezählt.'; }
							else if(STATUS['mode'] == 'STATUS') { this.DEV_LABEL_STATUS.text = STATUS['status']; }
							else { this.DEV_LABEL_STATUS.text = ' Abfrage erfolgreich '; }
						}
					}
					
					/** inform dev **/
				}
				else if(STATUS['type'] == 'amfFault')
				{
					/** inform dev **/
					if(STATUS['mode'] == 'READ')	{ this.DEV_LABEL_STATUS.text = 'Fehler beim laden der Daten.'; }
					else if(STATUS['mode'] == 'INSERT')	{ this.DEV_LABEL_STATUS.text = 'Fehler beim speichern.'; }
					else if(STATUS['mode'] == 'UPDATE')	{ this.DEV_LABEL_STATUS.text = 'Fehler beim aktualisieren.'; }
					else if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = 'Fehler bei SQL-Abfrage.'; }
					else if(STATUS['mode'] == '')		{ this.DEV_LABEL_STATUS.text = 'Fehler in AMFPHP Script oder SQL-Abfrage.'; }
					else if(STATUS['mode'] == 'COUNT_ELEMENTS')		{ this.DEV_LABEL_STATUS.text = 'Zähen der Einträge fehlgeschlagen.'; }
					else if(STATUS['mode'] == 'STATUS') { this.DEV_LABEL_STATUS.text = STATUS['status']; }
					else { this.DEV_LABEL_STATUS.text = ' Abfrage fehlgeschlagen.'; }
				}
				else // hat weder ARRAY noch fault properties...... gehe davon aus dass es ein ARRAY ist.
				{
					/** inform dev **/
					if(STATUS['mode'] == 'READ') 	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich geladen.'; }
					else if(STATUS['mode'] == 'INSERT')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich gespeichert.'; }
					else if(STATUS['mode'] == 'UPDATE')	{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Daten erfolgreich aktualisisert.'; }
					else if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = STATUS['mode']+' Abfrage erfolgreich.'; }
					else if(STATUS['mode'] == 'COUNT_ELEMENTS') { this.DEV_LABEL_STATUS.text = STATUS['mode']+' Elemente erfolgreich gezählt.'; }
					else if(STATUS['mode'] == 'STATUS') { this.DEV_LABEL_STATUS.text = STATUS['status']; }
					else { this.DEV_LABEL_STATUS.text = ' Abfrage erfolgreich '; }
				}
				
				DEV_LABEL_STATUS.text = DEV_LABEL_STATUS.text+':'+STATUS['status'];
			}
		}

		/** how much time is gone between the last package was received and the current package
		 * necessary 
		 * **/
		public var time_between_packets:Number = 0;
		/** setzt progress an einem progress bar ala custom
		 
		 <mx:ApplicationControlBar width="400">
		 <mx:HBox id="loading_bar" width="100%" horizontalGap="0">
		 <mx:Button id="TO_LOAD" fillColors="{['#ff0000', '#ff0000', '#ff0000', '#ff0000']}" width="100%" label="LOADING......"/>
		 <mx:Button id="LOADED" fillColors="{['#00ff00', '#00ff00', '#00ff00', '#00ff00']}" width="0%" label=".....LOADED!"/>
		 </mx:HBox>
		 </mx:ApplicationControlBar>
		 
		 *  **/
		public function FUNC_SET_PROGRESS(CURRENT:Number,TOTAL:Number,loading_bar:Object):void
		{
			if(loading_bar != null)
			{
				var ONE_PERCENT:Number = TOTAL / 100;
				var PERCENT:Number = CURRENT / ONE_PERCENT;
				
				PERCENT = c_formaters_inst.FormatFloat(PERCENT);
				
				var TIME_DIFF:Number = (new Date().getTime()) - time_between_packets; // calc diff between current and last package arrival
				
				var SPEED:Number = c_formaters_inst.FormatFloat(parseInt(OBJECT_PAGING_XML['packet_size']) / (TIME_DIFF/1000));
				
				time_between_packets = new Date().getTime(); // set current time
				
				var ONE_PERCENT_WIDTH:Number = loading_bar.width / 100;

				var BUTTON_TO_LOAD:Button = loading_bar.getChildAt(0) as Button;
				var BUTTON_LOADED:Button = loading_bar.getChildAt(1) as Button;
				
				BUTTON_LOADED.width = ONE_PERCENT_WIDTH * PERCENT;
				
				BUTTON_TO_LOAD.width = loading_bar.width - BUTTON_LOADED.width;
				
				try
				{
					var TOOLTIP:String = CURRENT+' von '+TOTAL+' geladen. '+SPEED+' Einträge pro Sekunde';
					BUTTON_LOADED['toolTip'] = BUTTON_TO_LOAD['toolTip'] = loading_bar['toolTip'] = TOOLTIP;
				}
				catch(e:Error)
				{
					
				}
			}
		}

		/** maybe you want to set your own LABEL_STATUS... otherwise it will be overwritten
		 * 
		 * if:
		 * currentTarget = sdk3.components.remoteService.remoteService_java (@1a9a06a1)	
		 * go like this:
		 * event.currentTarget["DO_NOT_UPDATE_USER_LABEL_STATUS"] = true;
		 * **/
		private var _DO_NOT_UPDATE_USER_LABEL_STATUS:Boolean = false;
		public function set DO_NOT_UPDATE_USER_LABEL_STATUS(DO_NOT_UPDATE_USER_LABEL_STATUS_var:Boolean):void
		{
			this._DO_NOT_UPDATE_USER_LABEL_STATUS = DO_NOT_UPDATE_USER_LABEL_STATUS_var;
		}
		public function get DO_NOT_UPDATE_USER_LABEL_STATUS():Boolean
		{
			return this._DO_NOT_UPDATE_USER_LABEL_STATUS;
		}
		
		/** maybe you want to set your own LABEL_STATUS... otherwise it will be overwritten
		 * 
		 * if:
		 * currentTarget = sdk3.components.remoteService.remoteService_java (@1a9a06a1)	
		 * go like this:
		 * event.currentTarget["DO_NOT_UPDATE_DEV_LABEL_STATUS"] = true;
		 * **/
		private var _DO_NOT_UPDATE_DEV_LABEL_STATUS:Boolean = false;
		public function set DO_NOT_UPDATE_DEV_LABEL_STATUS(DO_NOT_UPDATE_DEV_LABEL_STATUS_var:Boolean):void
		{
			this._DO_NOT_UPDATE_DEV_LABEL_STATUS = DO_NOT_UPDATE_DEV_LABEL_STATUS_var;
		}
		public function get DO_NOT_UPDATE_DEV_LABEL_STATUS():Boolean
		{
			return this._DO_NOT_UPDATE_DEV_LABEL_STATUS;
		}
		
		/** update labelstatus of user **/
		public function UPDATE_USER_LABEL_STATUS(STATUS:Object):void
		{
			if(DO_NOT_UPDATE_USER_LABEL_STATUS)
			{
				return;
			}

			/** update labelstatus **/
			if(USER_LABEL_STATUS != null)
			{
				if(STATUS['type'] == 'amfResult')
				{
					var ARRAY:Array = null;
					try
					{
						ARRAY = STATUS['result'];
					}
					catch(e:Error)
					{
					}
					
					/** inform user **/
					try
					{
						if(ARRAY.length == 0)
						{
							this.USER_LABEL_STATUS.text = 'Keine Daten vorhanden.';
						}
						else
						{
							if(STATUS['mode'] == 'READ') 	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich geladen.'; }
							if(STATUS['mode'] == 'INSERT')	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich gespeichert.'; }
							if(STATUS['mode'] == 'UPDATE')	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich aktualisisert.'; }
							if(STATUS['mode'] == 'SQL')		{ this.USER_LABEL_STATUS.text = 'Abfrage erfolgreich.'; }
						}
					}
					catch(e:Error)
					{
					}
					
					if(ARRAY == null)
					{
						if(STATUS['mode'] == 'READ') { this.USER_LABEL_STATUS.text = 'Keine Daten vorhanden.'; }
					}
					else
					{
						if(STATUS['mode'] == 'READ') 	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich geladen.'; }
						if(STATUS['mode'] == 'INSERT')	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich gespeichert.'; }
						if(STATUS['mode'] == 'UPDATE')	{ this.USER_LABEL_STATUS.text = 'Daten erfolgreich aktualisisert.'; }
						if(STATUS['mode'] == 'SQL')		{ this.USER_LABEL_STATUS.text = 'Abfrage erfolgreich.'; }
					}
				}
				else if(STATUS['type'] == 'amfFault')
				{
					/** inform user **/
					if(STATUS['mode'] == 'READ')	{ this.USER_LABEL_STATUS.text = 'Fehler beim laden der Daten.'; }
					if(STATUS['mode'] == 'INSERT')	{ this.USER_LABEL_STATUS.text = 'Fehler beim speichern.'; }
					if(STATUS['mode'] == 'UPDATE')	{ this.USER_LABEL_STATUS.text = 'Fehler beim aktualisieren.'; }
					if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = 'Fehler bei SQL-Abfrage.'; }
					if(STATUS['mode'] == '')		{ this.USER_LABEL_STATUS.text = 'Fehler in AMFPHP Script.'; }
					
				}
				else // hat weder ARRAY noch fault properties...... gehe davon aus dass es ein ARRAY ist.
				{
					/** inform user **/
					if(STATUS['mode'] == 'READ')  { this.USER_LABEL_STATUS.text = 'Daten erfolgreich geladen.';}
					if(STATUS['mode'] == 'INSERT'){ this.USER_LABEL_STATUS.text = 'Daten erfolgreich gespeichert.';}
					if(STATUS['mode'] == 'UPDATE'){ this.USER_LABEL_STATUS.text = 'Daten erfolgreich aktualisiert.';}
					if(STATUS['mode'] == 'SQL')		{ this.DEV_LABEL_STATUS.text = 'Fehler bei SQL-Abfrage.'; }
				}
			}
		}

		/** escapes MySQL-Sensitive Characters like \x00, \n, \r, \, ', " and \x1a.
		 * http://de2.php.net/manual/en/function.mysql-real-escape-string.php
		 * mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string,
		 * which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.
		 **/
		public function mysql_real_escape_string(STRING:String):String
		{
			if(c_OBJECT_inst.not_empty(STRING))
			{
				var EVILSTUFF:Array = ['damn\x00','damn\ndamn','damn\rdamn','damn\\damn','damn\'damn','damn\"damn','damn\x1adamn'];
				// list of characters where
				var LIST:Array = ['\x00','\n','\r','\\','\'','\"','\x1a'];
				var UNESCAPED_STRING:String = '';
				LENGTH = LIST.length;
				for(counter = 0;!(counter == LENGTH);counter++)
				{
					UNESCAPED_STRING = LIST[counter];
					STRING = STRING.replace(UNESCAPED_STRING,'\\'+UNESCAPED_STRING);
				}
				
				// testing
				for(counter = 0;!(counter == LENGTH);counter++)
				{
					var LENGTH2:int = EVILSTUFF.length;
					for(var counter2:int = 0;!(counter2 == LENGTH);counter2++)
					{
						UNESCAPED_STRING = LIST[counter];
						var EVIL_STIRNG:String = EVILSTUFF[counter2];
						EVIL_STIRNG = EVIL_STIRNG.replace(EVIL_STIRNG,'\\'+UNESCAPED_STRING);
					}
				}
			}

			return STRING;
		}
		
		/** will serialize the data of an array/object to a string.
		 * modes:
		 * 'excel with escaping' -> all special chars used as delimiters will be escaped with a /, /; /=
		 * 'excel' -> key1,key2,key3;value1,value2,value3;
		 * 'xeml' -> not implemented yet
		 **/
		public function serialize(OBJECT:Object,mode:String = 'excel with escaping'):String
		{
			var SERIALIZED_DATA:String = ''; 
			if(c_OBJECT_inst.not_empty(OBJECT))
			{
				var RSU:remoteService_utility = new remoteService_utility();

				if(OBJECT is Array)
				{
					var DATA_ARRAY:Array = OBJECT as Array;
	
					if(mode == 'excel with escaping')
					{
						for(var counter:int = 0;!(counter == DATA_ARRAY.length);counter++)
						{
							var ELEMENT:Object = DATA_ARRAY[counter];
							for(var KEY:String in ELEMENT)
							{
								SERIALIZED_DATA = SERIALIZED_DATA+RSU.mysql_real_escape_string(KEY)+'/='+RSU.mysql_real_escape_string(ELEMENT[KEY])+'/,';
							}

							SERIALIZED_DATA = SERIALIZED_DATA+'/;';
						}
					}
				}
				else if(OBJECT is user)
				{
					var USER:user = OBJECT as user;
					var USER_inst:Object = USER.toObject();
					if(mode == 'excel with escaping')
					{
						for(var KEY:String in USER_inst)
						{
							if(KEY == "chatUserGroups")
							{
								SERIALIZED_DATA = SERIALIZED_DATA+RSU.mysql_real_escape_string(KEY)+'/='+RSU.mysql_real_escape_string(USER_inst[KEY])+'/,';
							}
							else
							{
								SERIALIZED_DATA = SERIALIZED_DATA+RSU.mysql_real_escape_string(KEY)+'/='+RSU.mysql_real_escape_string(USER_inst[KEY])+'/,';
							}
						}
					}
					SERIALIZED_DATA = SERIALIZED_DATA+'/;';
				}
				else if(OBJECT is Object)
				{
					var OBJECT_inst:Object = OBJECT as Object;
					if(mode == 'excel with escaping')
					{
						for(var KEY:String in OBJECT_inst)
						{
							SERIALIZED_DATA = SERIALIZED_DATA+RSU.mysql_real_escape_string(KEY)+'/='+RSU.mysql_real_escape_string(OBJECT_inst[KEY])+'/,';
						}
						
						SERIALIZED_DATA = c_STRING_inst.REMOVE_LAST_X_CHARS(SERIALIZED_DATA,2);
					}
					SERIALIZED_DATA = SERIALIZED_DATA+'/;';
				}
			}
			
			return SERIALIZED_DATA;
		}
	}
}